/*
 * @# PostsServiceImpl.java 2011-12-19 下午03:16:07
 * 
 * Copyright (C) 2010 - 2011 广州羿安信息科技有限公司
 * Guangzhou ianswer information technology co. ltd.
 * 
 * All rights reserved!
 */
package com.ianswer.px.posts.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.ianswer.common.orm.PublicDao;
import com.ianswer.common.util.time.DurationUtils;
import com.ianswer.common.util.time.SecondsUtils;
import com.ianswer.px.posts.entity.Post;
import com.ianswer.px.posts.entity.PostCondition;
import com.ianswer.px.posts.entity.PostData;
import com.ianswer.px.posts.entity.PostInbox;
import com.ianswer.px.posts.entity.PostRedisEntity;
import com.ianswer.px.posts.redis.PostRedis;
import com.ianswer.px.posts.service.PostService;
import com.ianswer.px.user.entity.UserBaseInfo;
import com.ianswer.px.user.redis.FigureRedis;
import com.ianswer.px.user.redis.UserRedis;
import com.ianswer.px.user.service.FollowService;

/**
 * @author lunx
 */
@Service("postService")
public class PostServiceImpl implements PostService {

	@Resource(name = "publicDao")
	private PublicDao publicDao;

	@Resource(name = "followService")
	private FollowService followService;

	@Override
	public void insert(Post post) {
		//1、插入博文到posts表，有附件则保存，并写入博主的inbox中
		Long post_id = (Long) publicDao.insert("posts.insert", post);
		attachment(post.getUserId(), post_id);
		PostInbox inbox = new PostInbox();
		inbox.setPostId(post_id);
		inbox.setUserId(post.getUserId());
		inbox.setCreatedAt(post.getCreatedAt());
		publicDao.insert("posts_inbox.insert", inbox);
		//TODO 同时需要写入mc的inbox

		//2、写入redis
		//更新 figure:[uid] 博文数: posts + 1
		FigureRedis.incrUNREAD(post.getUserId());
		//初始化 post:[pid]
		PostRedis.postInit(post, post_id);

		//3、遍历粉丝(目前是全量遍历，后续要考虑分段进行)，把新博文id插入到各个的inbox中
		//4、遍历粉丝时，若粉丝已有mc的inbox，则同时写入mc
		//5、@me
		try {
			opInbox(post, post_id);
			atMe();
		} catch (Exception ex) {
			//下推出问题时需要在系统中告警，但不报错给博主
			//TODO 要加Log
		}
	}

	private void attachment(long userId, long post_id) {
		//TODO 附件
	}

	/**
	 * 处理inbox
	 * @param userId
	 * @param post_id
	 */
	private void opInbox(Post post, long post_id) {
		List<Long> fans = followService.queryFansId(post.getUserId());
		PostInbox inbox1 = null;
		long createAt = post.getCreatedAt();
		for (Long fan_user_id : fans) {
			inbox1 = new PostInbox();
			inbox1.setPostId(post_id);
			inbox1.setUserId(fan_user_id);
			inbox1.setCreatedAt(createAt);
			publicDao.insert("posts_inbox.insert", inbox1);

			//TODO 有inbox缓存的粉丝，则入mc的inbox

			//更新 粉丝figure:[uid] 未读博文数: unread + 1
			FigureRedis.incrUNREAD(fan_user_id);
		}
	}

	private void atMe() {
		//TODO atMe
	}

	@Override
	public void delete(Long id) {
		publicDao.delete("posts.delete", id);
	}

	/**
	 * 取出来只有一个PostData
	 */
	@Override
	public PostData get(Long id) {
		return publicDao.querySingle("posts.getpost", id);
	}

	@Override
	public List<PostData> query(long userId) {
		long unReadNum = FigureRedis.getUnReadNumAndSetZero(userId);
		if (unReadNum <= 0)
			return null;
		PostCondition c = new PostCondition();
		c.setUserId(userId);
		c.setUnReadNum(unReadNum);
		List<PostData> l = publicDao.query("posts.news", c);
		opPostData(l,false);
		return l;
	}

	@Override
	public List<PostData> query(long userId, int skip, int max) {
		if (skip == 0) {
			//首页
			FigureRedis.setZeroUnReadNum(userId);
		}
		List<PostData> l = publicDao.query("posts.get", userId, skip, max);
		opPostData(l,false);
		return l;
	}
	
	@Override
	public List<PostData> queryPosts(long userId, int skip, int max) {
		List<PostData> l = publicDao.query("posts.getinfo", userId, skip, max);
		opPostData(l,false);
		return l;
	}

	/**
	 * 根据db查到的数据，结合redis中的数据，封装成返回给界面用的数据
	 * @param trans_stop_flag 防止因脏数据引起的无限递归或多层递归
	 */
	private void opPostData(List<PostData> l,boolean trans_stop_flag) {
		if (l == null || l.size() == 0) {
			l = null;
			return;
		}
		long now = SecondsUtils.seconds();
		for (PostData t : l) {
			t.setCreateAtStr(DurationUtils.seconds(now, t.getCreatedAt()));
			UserBaseInfo u = UserRedis.get(t.getUserId());

			if (u != null) {
				t.setEmail(u.getEmail());
				t.setNickName(u.getNickname());
				t.setUserType(u.getUserType());
				t.setAvatar(u.getAvatar());
				
				u = null;
			}

			PostRedisEntity p = PostRedis.get(t.getId());
			if (p != null) {
				t.setComments(p.getComments());
				t.setTransferred(p.getTransferred());
				if (!trans_stop_flag && p.getTranid() != null) {
					//表明此博文是转发微博，则要读出原始博文实体，并放到PostData实体中
					PostData temp = get(p.getTranid());//取出来只有一条
					List<PostData> templ = new ArrayList<PostData>();
					templ.add(temp);
					opPostData(templ,true);
					if (temp != null) {
						t.setTranPost(templ.get(0));
					}
				}
				p = null;
			}
		}
	}
}
